"""
订阅服务
处理订阅相关的业务逻辑
"""

import asyncio
import time
from typing import List, Dict, Any, Optional
import aiohttp

from ..storage import data_manager, SubscriptionRecord, SubscriptionServer, ModelInfo
from ..logger import logger
from ..config import config
from ..utils import retry_on_exception


class SubscriptionService:
    """订阅服务类"""
    
    def __init__(self):
        self.subscription_config = config.get_subscription_config()
        self.is_running = False
        self.check_task = None
        
    async def start(self):
        """启动订阅服务"""
        if self.is_running:
            return
            
        self.is_running = True
        
        if self.subscription_config.get('enabled', True):
            # 启动定期检查任务
            self.check_task = asyncio.create_task(self._periodic_check())
            logger.info("Subscription service started")
        else:
            logger.info("Subscription service is disabled")
            
    async def stop(self):
        """停止订阅服务"""
        self.is_running = False
        
        if self.check_task:
            self.check_task.cancel()
            try:
                await self.check_task
            except asyncio.CancelledError:
                pass
                
        logger.info("Subscription service stopped")
        
    async def _periodic_check(self):
        """定期检查订阅"""
        default_interval = self.subscription_config.get('default_check_interval', 1800)
        
        while self.is_running:
            try:
                await self.check_all_subscriptions()
                await asyncio.sleep(default_interval)
            except asyncio.CancelledError:
                break
            except Exception as e:
                logger.error(f"Error in periodic subscription check: {e}")
                await asyncio.sleep(60)  # 出错时等待1分钟再重试
                
    async def check_all_subscriptions(self):
        """检查所有活跃订阅"""
        try:
            # 获取所有活跃订阅
            subscriptions = await data_manager.get_subscriptions()
            active_subscriptions = [
                sub for sub in subscriptions 
                if sub.status == "active"
            ]
            
            if not active_subscriptions:
                logger.debug("No active subscriptions to check")
                return
                
            logger.info(f"Checking {len(active_subscriptions)} active subscriptions")
            
            # 按服务器分组订阅
            subscriptions_by_server = {}
            for subscription in active_subscriptions:
                server_id = subscription.server_id
                if server_id not in subscriptions_by_server:
                    subscriptions_by_server[server_id] = []
                subscriptions_by_server[server_id].append(subscription)
            
            # 并发检查各个服务器
            max_concurrent = self.subscription_config.get('max_concurrent_checks', 5)
            semaphore = asyncio.Semaphore(max_concurrent)
            
            tasks = []
            for server_id, server_subscriptions in subscriptions_by_server.items():
                task = asyncio.create_task(
                    self._check_server_subscriptions(semaphore, server_id, server_subscriptions)
                )
                tasks.append(task)
            
            # 等待所有检查完成
            await asyncio.gather(*tasks, return_exceptions=True)
            
        except Exception as e:
            logger.error(f"Failed to check subscriptions: {e}")
            
    async def _check_server_subscriptions(
        self, 
        semaphore: asyncio.Semaphore, 
        server_id: str, 
        subscriptions: List[SubscriptionRecord]
    ):
        """检查特定服务器的订阅"""
        async with semaphore:
            try:
                # 获取服务器信息
                server = await data_manager.get_server_by_id(server_id)
                if not server:
                    logger.warning(f"Server {server_id} not found, skipping subscriptions")
                    return
                
                if server.status != "online":
                    logger.debug(f"Server {server.name} is offline, skipping checks")
                    return
                
                # 获取服务器上的模型列表
                server_models = await self._fetch_server_models(server)
                if server_models is None:
                    logger.warning(f"Failed to fetch models from server {server.name}")
                    return
                
                # 检查每个订阅
                for subscription in subscriptions:
                    await self._check_subscription_updates(subscription, server_models)
                    
            except Exception as e:
                logger.error(f"Error checking server {server_id} subscriptions: {e}")
                
    @retry_on_exception(max_retries=3, delay=1.0)
    async def _fetch_server_models(self, server: SubscriptionServer) -> Optional[List[Dict[str, Any]]]:
        """从服务器获取模型列表"""
        try:
            timeout = aiohttp.ClientTimeout(
                total=self.subscription_config.get('request_timeout', 30)
            )
            
            headers = {}
            if server.api_key:
                headers['Authorization'] = f'Bearer {server.api_key}'
            
            async with aiohttp.ClientSession(timeout=timeout) as session:
                models_url = f"{server.url.rstrip('/')}/api/v1/models"
                
                async with session.get(models_url, headers=headers) as response:
                    if response.status == 200:
                        data = await response.json()
                        return data.get('models', [])
                    else:
                        logger.warning(f"Server {server.name} returned status {response.status}")
                        return None
                        
        except Exception as e:
            logger.debug(f"Failed to fetch models from {server.name}: {e}")
            raise
            
    async def _check_subscription_updates(
        self, 
        subscription: SubscriptionRecord, 
        server_models: List[Dict[str, Any]]
    ):
        """检查订阅的模型更新"""
        try:
            # 查找匹配的模型
            matching_models = []
            
            for model_data in server_models:
                model_name = model_data.get('name', '')
                model_version = model_data.get('version', '')
                
                # 检查模型名称匹配
                if model_name != subscription.model_name:
                    continue
                
                # 检查版本匹配
                if subscription.model_version == "*":
                    # 通配符匹配所有版本
                    matching_models.append(model_data)
                elif subscription.model_version == model_version:
                    # 精确版本匹配
                    matching_models.append(model_data)
            
            # 更新订阅的最后检查时间
            subscription.last_checked = time.time()
            await data_manager.update_subscription(subscription)
            
            # 如果找到新模型或更新，发送通知
            if matching_models:
                await self._notify_subscription_updates(subscription, matching_models)
                
        except Exception as e:
            logger.error(f"Error checking subscription {subscription.id}: {e}")
            
    async def _notify_subscription_updates(
        self, 
        subscription: SubscriptionRecord, 
        models: List[Dict[str, Any]]
    ):
        """通知订阅更新"""
        try:
            # 这里可以实现各种通知方式
            for channel in subscription.notification_channels:
                if channel == "webhook" and subscription.callback_url:
                    await self._send_webhook_notification(subscription, models)
                elif channel == "websocket":
                    await self._send_websocket_notification(subscription, models)
                    
        except Exception as e:
            logger.error(f"Error sending notifications for subscription {subscription.id}: {e}")
            
    async def _send_webhook_notification(
        self, 
        subscription: SubscriptionRecord, 
        models: List[Dict[str, Any]]
    ):
        """发送Webhook通知"""
        try:
            if not subscription.callback_url:
                return
                
            payload = {
                "event": "model_update",
                "subscription_id": subscription.id,
                "client_id": subscription.client_id,
                "model_name": subscription.model_name,
                "models": models,
                "timestamp": time.time()
            }
            
            timeout = aiohttp.ClientTimeout(total=30)
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.post(
                    subscription.callback_url, 
                    json=payload,
                    headers={"Content-Type": "application/json"}
                ) as response:
                    if response.status == 200:
                        logger.info(f"Webhook notification sent to {subscription.client_name}")
                    else:
                        logger.warning(f"Webhook failed with status {response.status}")
                        
        except Exception as e:
            logger.error(f"Failed to send webhook notification: {e}")
            
    async def _send_websocket_notification(
        self, 
        subscription: SubscriptionRecord, 
        models: List[Dict[str, Any]]
    ):
        """发送WebSocket通知"""
        # TODO: 实现WebSocket通知
        logger.debug(f"WebSocket notification for subscription {subscription.id}")
        
    async def create_subscription(
        self, 
        client_id: str, 
        client_name: str, 
        model_name: str, 
        model_version: str, 
        server_id: str,
        auto_update: bool = True,
        notification_channels: List[str] = None,
        callback_url: Optional[str] = None
    ) -> str:
        """创建新订阅"""
        try:
            # 验证服务器存在
            server = await data_manager.get_server_by_id(server_id)
            if not server:
                raise ValueError(f"Server {server_id} not found")
            
            # 检查重复订阅
            existing_subscriptions = await data_manager.get_subscriptions()
            for existing_sub in existing_subscriptions:
                if (existing_sub.client_id == client_id and
                    existing_sub.model_name == model_name and
                    existing_sub.server_id == server_id and
                    existing_sub.status == "active"):
                    raise ValueError("Active subscription already exists")
            
            # 创建订阅记录
            from ..utils import generate_id
            
            subscription = SubscriptionRecord(
                id=generate_id(),
                client_id=client_id,
                client_name=client_name,
                model_name=model_name,
                model_version=model_version or "*",
                server_id=server_id,
                subscribed_at=time.time(),
                last_checked=time.time(),
                status="active",
                auto_update=auto_update,
                notification_channels=notification_channels or ["webhook"],
                callback_url=callback_url
            )
            
            await data_manager.add_subscription(subscription)
            
            logger.info(f"Created subscription: {client_name} -> {model_name}")
            return subscription.id
            
        except Exception as e:
            logger.error(f"Failed to create subscription: {e}")
            raise


# 全局订阅服务实例
subscription_service = SubscriptionService()
